{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Energy system optimisation with oemof - how to collect and store results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import necessary modules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from oemof.solph import (Sink, Source, Transformer, Bus, Flow, Model,\n",
    "                         EnergySystem)\n",
    "import oemof.outputlib as outputlib\n",
    "import pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Specify solver"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "solver = 'cbc'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create an energy system and optimize the dispatch at least costs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# initialize and provide data\n",
    "datetimeindex = pd.date_range('1/1/2016', periods=24*10, freq='H')\n",
    "energysystem = EnergySystem(timeindex=datetimeindex)\n",
    "filename = 'input_data.csv'\n",
    "data = pd.read_csv(filename, sep=\",\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create and add components to energysystem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# resource buses\n",
    "bcoal = Bus(label='coal', balanced=False)\n",
    "bgas = Bus(label='gas', balanced=False)\n",
    "boil = Bus(label='oil', balanced=False)\n",
    "blig = Bus(label='lignite', balanced=False)\n",
    "\n",
    "# electricity and heat\n",
    "bel = Bus(label='bel')\n",
    "bth = Bus(label='bth')\n",
    "\n",
    "energysystem.add(bcoal, bgas, boil, blig, bel, bth)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# an excess and a shortage variable can help to avoid infeasible problems\n",
    "energysystem.add(Sink(label='excess_el', inputs={bel: Flow()}))\n",
    "# shortage_el = Source(label='shortage_el',\n",
    "#                      outputs={bel: Flow(variable_costs=200)})\n",
    "\n",
    "# sources\n",
    "energysystem.add(Source(label='wind', outputs={bel: Flow(\n",
    "    actual_value=data['wind'], nominal_value=66.3, fixed=True)}))\n",
    "\n",
    "energysystem.add(Source(label='pv', outputs={bel: Flow(\n",
    "    actual_value=data['pv'], nominal_value=65.3, fixed=True)}))\n",
    "\n",
    "# demands (electricity/heat)\n",
    "energysystem.add(Sink(label='demand_el', inputs={bel: Flow(\n",
    "    nominal_value=85, actual_value=data['demand_el'], fixed=True)}))\n",
    "\n",
    "energysystem.add(Sink(label='demand_th',\n",
    "                 inputs={bth: Flow(nominal_value=40,\n",
    "                                   actual_value=data['demand_th'],\n",
    "                                   fixed=True)}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# power plants\n",
    "energysystem.add(Transformer(\n",
    "    label='pp_coal',\n",
    "    inputs={bcoal: Flow()},\n",
    "    outputs={bel: Flow(nominal_value=20.2, variable_costs=25)},\n",
    "    conversion_factors={bel: 0.39}))\n",
    "\n",
    "energysystem.add(Transformer(\n",
    "    label='pp_lig',\n",
    "    inputs={blig: Flow()},\n",
    "    outputs={bel: Flow(nominal_value=11.8, variable_costs=19)},\n",
    "    conversion_factors={bel: 0.41}))\n",
    "\n",
    "energysystem.add(Transformer(\n",
    "    label='pp_gas',\n",
    "    inputs={bgas: Flow()},\n",
    "    outputs={bel: Flow(nominal_value=41, variable_costs=40)},\n",
    "    conversion_factors={bel: 0.50}))\n",
    "\n",
    "energysystem.add(Transformer(\n",
    "    label='pp_oil',\n",
    "    inputs={boil: Flow()},\n",
    "    outputs={bel: Flow(nominal_value=5, variable_costs=50)},\n",
    "    conversion_factors={bel: 0.28}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# combined heat and power plant (chp)\n",
    "energysystem.add(Transformer(\n",
    "    label='pp_chp',\n",
    "    inputs={bgas: Flow()},\n",
    "    outputs={bel: Flow(nominal_value=30, variable_costs=42),\n",
    "             bth: Flow(nominal_value=40)},\n",
    "    conversion_factors={bel: 0.3, bth: 0.4}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# heat pump with a coefficient of performance (COP) of 3\n",
    "b_heat_source = Bus(label='b_heat_source')\n",
    "energysystem.add(b_heat_source)\n",
    "\n",
    "energysystem.add(Source(label='heat_source', outputs={b_heat_source: Flow()}))\n",
    "\n",
    "cop = 3\n",
    "energysystem.add(Transformer(\n",
    "    label='heat_pump',\n",
    "    inputs={bel: Flow(),\n",
    "            b_heat_source: Flow()},\n",
    "    outputs={bth: Flow(nominal_value=10)},\n",
    "    conversion_factors={bel: 1/3, b_heat_source: (cop-1)/cop}))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create optimization model based on energy_system\n",
    "optimization_model = Model(energysystem=energysystem)\n",
    "\n",
    "# solve problem\n",
    "optimization_model.solve(solver=solver,\n",
    "                         solve_kwargs={'tee': True, 'keepfiles': False})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Write results into energysystem.results object for later"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "energysystem.results['main'] = outputlib.processing.results(optimization_model)\n",
    "energysystem.results['meta'] = outputlib.processing.meta_results(optimization_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "string_results = outputlib.views.convert_keys_to_strings(energysystem.results['main'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save results - Dump the energysystem (to ~/home/user/.oemof by default)\n",
    "Specify path and filename if you do not want to overwrite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "energysystem.dump(dpath=None, filename=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "p3",
   "language": "python",
   "name": "p3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
